package web;

import file.WebShare;
import hypercast.I_LogicalAddress;

import java.io.*;
import java.util.*;
import java.awt.Desktop;

import ctrl.Control;
import intf.RunOSXcmd;

public class Explorer {
	private Control ctrl;
	ArrayList<String> sites = new ArrayList<String>();

	// ####String siteName;
	// ####boolean onSiteListing;
	Cache cache = new Cache(ctrl);

	public Explorer(Control g) {
		ctrl = g;
		File dir = new File("cache");
		dir.mkdir();
	}

	public void cache(String s) throws IOException {

		ctrl.println("Caching " + s + " ...");
		cache.currentWeb(s);
	}

	public void explore(int i) {
		if (i < 0) {
			update();
			ctrl.println("Site Listing Refreshed.");
		} else {
			String p = sites.get(i);

			if (Desktop.isDesktopSupported()) {
				Desktop myDesktop = Desktop.getDesktop();

				// get file name .. then
				String filePath = "cache/" /* + siteName */+ p + "/index.html";
				File file = new File(filePath);
				if (myDesktop.isSupported(Desktop.Action.OPEN)) {

					try { // opens with default browser
						myDesktop.open(file);
					} catch (IOException e) {
						System.out.println("@Explorer - IOException: " + e.getMessage());
					}
				} else {
					ctrl.println("Error 381: Desktop.Action.OPEN is not supported.");
				}
			} else {
				ctrl.println("Error 382: Sorry, this feature is not supported on this machine.");
			}
			update();
		}
	}

	public void update() {
		// Directory path here
		String path = "./cache";
		File folder = new File(path);
		File[] listOfFiles = folder.listFiles();

		for (int i = 0; i < listOfFiles.length; i++) {
			// adding check for hidden files -yh
			if (!listOfFiles[i].isHidden()) {
				if(!sites.contains(listOfFiles[i].getName())){
					ctrl.addSite(listOfFiles[i].getName());
					sites.add(listOfFiles[i].getName());
				}
			}
			// else... don't do anything
		}
	}
	
	//web site updater
	public void start(){
		(new Thread(new Updater())).start();
	}
	
	//get all neighbors and request for web sites
	private class Updater implements Runnable {
		public void run() {
			
			//wait 20 seconds before starting to request pages
			try {
				Thread.sleep(20000);
			} catch (InterruptedException e) {
				System.out.println("@Explorer - InterruptedException: " + e.getMessage());
			}
			
			while (ctrl.getNet().connected) {
				I_LogicalAddress[] n = ctrl.getNet().Neighbours();
				for(int i = 0; i < n.length && ctrl.getNet().connected; i++){
					request(n[i]);
					try {
						Thread.sleep(15000);
					} catch (InterruptedException e) {
						System.out.println("@Explorer - InterruptedException: " + e.getMessage());
					}
				}
				try {
					Thread.sleep(500); //wait 30 seconds before asking again
				} catch (InterruptedException e) {
					System.out.println("@Explorer - InterruptedException: " + e.getMessage());
				}
			}
		}
	}

	public void request(I_LogicalAddress to) {
		String myPages = "";
		for (int i = 0; i < sites.size(); i++) {
			myPages = myPages.concat(" ");
			myPages = myPages.concat(sites.get(i));
		}
		ctrl.getNet().sendBytes(myPages.getBytes(), 5, to);
	}

	//Receive request from neighbors to share local sites to him
	//Compare what i have with what my neighbor has
	public void share(String pages, I_LogicalAddress from) {
		ArrayList<String> diff = new ArrayList<String>(sites);
		for (int i = 0; i < diff.size(); i++) {
			if (pages.contains(diff.get(i))) {
				diff.remove(i);
				i--;
			}
		}

		if (diff.size() > 0) {
			String name = "sendArch" + from.toString() + ".zip";
			File target = new File(name);
			File directory = new File("cache");
			int returnCode = 0;
			try {
				returnCode = ZipUtility.zipDirectory(directory, target, diff);
			} catch (Exception e) {
				returnCode = -1;
				System.out.println("@Explorer - Exception: Error with the ZipUtility!");
			}
			if (returnCode == 0) {
				WebShare wsr = new WebShare(ctrl, name, from);
				wsr.action();
			}
			else {
				System.out.println("@Explorer - Error with the ZipUtility with return code=" + returnCode);
			}
		} //else no need to send anything
	}

	public void receive(byte[] data, String from) {
		String name = "recArch" + from + ".zip";
		File arch = new File(name);
		FileOutputStream fos;
		try {
			fos = new FileOutputStream(arch.getPath());
			fos.write(data);
			fos.close();
			
			String OS = System.getProperty("os.name").toLowerCase();
			
			if (OS.indexOf("windows") >= 0){
				File directory = new File("cache");
				ZipUtility.unzip(arch, directory);
				arch.delete();
			}
			else if (OS.indexOf("mac") >= 0) {
				String cmd = "unzip -q -n " + name + " -d cache";
				RunOSXcmd.run(cmd);
				cmd = "rm " + name;
				RunOSXcmd.run(cmd);
			}
			else if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0
					|| OS.indexOf("aix") > 0) {
				System.out.println("@Explorer: Needs implementation for current OS.");
				ctrl.println("System Error::Current OS not supported unzipping files.");
			}
			else {
				System.out.println("@Explorer: Needs implementation for current OS.");
				ctrl.println("System Error::Current OS not supported unzipping files.");
			}
			

			
			ctrl.println("Received new websites!");
		} catch (Exception e) {
			ctrl.println("Error in receiving websites!");
			System.out.println("@Explorer - Exception: " + e.getMessage());
		}
		arch.delete();
		update();
	}
}
